﻿using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Rest;
using Newtonsoft.Json.Linq;
using RapidSalesAdminPortalAPI.DataAccess;
using RapidSalesAdminPortalAPI.Models;
using ServiceReference2;
using ServiceReference4;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using WebAPI.Services;

namespace RapidSalesAdminPortalAPI.Services
{
    public interface ISoapService
    {
        public Task<string> Login();
        public Task<LoginResponse> GetLoginResponse();
        public Task<string> GetToken();
        public Task<string> RequestAsync(string requestUrl, string meothName, Dictionary<string, object> args);
        public Task<string> FindB2BAccountProduct(string AAcountAK);
        public Task<List<EventTimeSlotDto>> SearchPerformance(string EVENTAK);
    }

    public class SoapService : ISoapService
    {
        private readonly ILogger _logger;
        private readonly IConfiguration Configuration;
        private IWsAPIAccountSoap _apiAccountService;

        public SoapService(ILogger<ISoapService> logger
            ,IConfiguration configuration,
            IWsAPIAccountSoap apiAccountService)
        {
            _logger = logger;
            Configuration = configuration;
            _apiAccountService = apiAccountService;
        }

        public async Task<string> Login()
        {
            try
            {
                var requestUrl = Configuration["RequestUrl"];
                var aUsername = Configuration["AUsername"];
                var aPsw = Configuration["APsw"];

                var args = new Dictionary<string, object>();
                args.Add("AUsername", aUsername);
                args.Add("APsw", aPsw);
                string meothName = "B2BAccountLogIn";   //服务的方法名
                requestUrl = requestUrl + "IWsAPIAccount.asmx?op=" + meothName;
                var httpClientHandler = new HttpClientHandler
                {
                    ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true
                };

                StringBuilder contentString = new StringBuilder();

                foreach (var item in args)
                {
                    contentString.Append($"<{item.Key}>{item.Value}</{item.Key}>");
                }
                string contentValue = contentString.ToString();
                string content = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" 
xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                   <soap:Body>
                     <{meothName} xmlns=""http://tempuri.org/"">
                         {contentValue}
                     </{meothName}>
                 </soap:Body>
              </soap:Envelope>";
                HttpContent httpContent = new StringContent(content, Encoding.UTF8, "text/xml");

                HttpClient client = new HttpClient(httpClientHandler);

                var response = await client.PostAsync(requestUrl, httpContent);
                var responseXml = await response.Content.ReadAsStringAsync();
                JObject obj = response.GetHeadersAsJson();// ["HeaderSrtore"]["Token"].ToString();
                if (obj != null)
                {
                    return obj?["Token"].ToString();
                }
                return string.Empty;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
                return string.Empty;
            }
        }
        public async Task<LoginResponse> GetLoginResponse()
        {
            var response = new LoginResponse();
            try
            {
                var AUsername = Configuration["AUsername"];
                var APsw = Configuration["APsw"];

                var request = new B2BAccountLogInRequest()
                {
                    AUsername = AUsername,
                    APsw = APsw
                };
                var result = await _apiAccountService.B2BAccountLogInAsync(request);
                string token = await GetToken();
                if (string.IsNullOrWhiteSpace(token))
                {
                    return null;
                }

                response.Toekn = token;
                response.B2BAccountLogin = result.@return;
                return response;
            }
            catch (Exception ex)
            {
                return response;
            }
        }
        public async Task<string> GetToken()
        {
            try
            {
                var requestUrl = Configuration["RequestUrl"];
                var aUsername = Configuration["AUsername"];
                var aPsw = Configuration["APsw"];

                var dic = new Dictionary<string, object>();
                dic.Add("AUsername", aUsername);
                dic.Add("APsw", aPsw);
                string meothName = "B2BAccountLogIn";   //服务的方法名
                requestUrl = requestUrl + "IWsAPIAccount.asmx?op=" + meothName;
                var httpClientHandler = new HttpClientHandler
                {
                    ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true
                };

                StringBuilder contentString = new StringBuilder();

                foreach (var item in dic)
                {
                    contentString.Append($"<{item.Key}>{item.Value}</{item.Key}>");
                }
                string contentValue = contentString.ToString();
                string content = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" 
xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                   <soap:Body>
                     <{meothName} xmlns=""http://tempuri.org/"">
                         {contentValue}
                     </{meothName}>
                 </soap:Body>
              </soap:Envelope>";
                HttpContent httpContent = new StringContent(content, Encoding.UTF8, "text/xml");

                HttpClient client = new HttpClient(httpClientHandler);

                var response = await client.PostAsync(requestUrl, httpContent);
                //var responseXml = await response.Content.ReadAsStringAsync();

                //XmlSerializer serializer = new XmlSerializer(typeof(B2BAccountLogInResponse));
                //using (StringReader reader = new StringReader(responseXml))
                //{
                //    B2BAccountLogInResponse data = (B2BAccountLogInResponse)serializer.Deserialize(reader);
                //}
                JObject obj = response.GetHeadersAsJson();// ["HeaderSrtore"]["Token"].ToString();
                if (obj != null)
                {
                    return obj?["Token"].ToString();
                }
                return string.Empty;
            }
            catch (Exception ex)
            {
                return string.Empty;
            }
        }
        public async Task<string> RequestAsync(string requestUrl, string meothName, Dictionary<string, object> dic)
        {
            var token = await Login();

            if (string.IsNullOrWhiteSpace(token)) 
            {
                return null;
            }

            var httpClientHandler = new HttpClientHandler
            {
                ServerCertificateCustomValidationCallback = (message, cert, chain, error) => true
            };

            StringBuilder contentString = new StringBuilder();

            foreach (var item in dic)
            {
                contentString.Append($"<{item.Key}>{item.Value}</{item.Key}>");
            }
            string contentValue = contentString.ToString();
            string content = $@"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance"" 
xmlns:xsd=""http://www.w3.org/2001/XMLSchema"" xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/"">
                   <soap:Body>
                     <{meothName} xmlns=""http://tempuri.org/"">
                         {contentValue}
                     </{meothName}>
                 </soap:Body>
              </soap:Envelope>";
            HttpContent httpContent = new StringContent(content, Encoding.UTF8, "text/xml");

            HttpClient client = new HttpClient(httpClientHandler);
            client.DefaultRequestHeaders.Add("Token", token);

            var response = await client.PostAsync(requestUrl, httpContent);
            var responseStr = await response.Content.ReadAsStringAsync();
            //var error = doc.Descendants(JetPlanCDBSoap.ErrorText).FirstOrDefault();
            //if (error != null)
            //{
            //    throw new Exception(error.Value);
            //}
            return responseStr;
        }
        public async Task<string> FindB2BAccountProduct(string AAccountAK)
        {
            var requestUrl = Configuration["RequestUrl"];
            var dic = new Dictionary<string, object>();
            dic.Add("AAccountAK", AAccountAK);
            string meothName = "FindB2BAccountProduct";   //服务的方法名
            requestUrl = requestUrl + "IWsAPIProduct.asmx?op=" + meothName;

            var xmlStr = await RequestAsync(requestUrl, meothName, dic);
            return xmlStr;
        }
        public async Task<List<EventTimeSlotDto>> SearchPerformance(string EVENTAK)
        {
            var loginResp = await GetLoginResponse();
            var clientPerformance = new WsAPIPerformanceSoapClient(new BasicHttpsBinding() { MaxReceivedMessageSize = 2147483647 }, new EndpointAddress(Configuration["AsmxUrl:PerformanceApiUrl"]));
    
            var list =new List<EventTimeSlotDto>();
            using (var operationContextScopePer = new OperationContextScope(clientPerformance.InnerChannel))
            {
                // 添加HTTP请求头  
                var httpRequestProperty = new HttpRequestMessageProperty();
                httpRequestProperty.Headers["token"] = loginResp?.Toekn;

                OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty;
                var PAGEREQ = new PAGEREQ()
                {
                    PAGEINDEX = "1",
                    PAGESIZE = "500",
                    SORTFIELD = "DATETIME",
                    SORTDIRECTION = "ASC",
                };
                var BASEDATEFILTER = new BASEDATEFILTER()
                {
                    FROM = DateTime.Now.ToString("yyyy-MM-dd"),
                    TO = DateTime.Now.ToString("yyyy-MM-dd"),
                };
                var performance = await clientPerformance.SearchPerformanceAsync(EVENTAK, "true", "", "", "", PAGEREQ, BASEDATEFILTER, null);
                if (performance != null && performance.@return != null && performance.@return.ERROR != null && performance.@return.ERROR.CODE == "200")
                {
                    if (performance.@return.PERFORMANCELIST != null && performance.@return.PERFORMANCELIST.Length > 0)
                    {
                        foreach (var item in performance.@return.PERFORMANCELIST)
                        {
                            var eventTimeSlots = new EventTimeSlotDto()
                            {
                                EventAk = EVENTAK,
                                StartDateTime = Convert.ToDateTime(item.DATETIME),
                                EndDateTime = Convert.ToDateTime(item.ENDDATETIME),
                                OpeningTime = item.OPENINGTIME,
                                ClosingTime = item.CLOSINGTIME,
                                IsFullDay = Convert.ToDateTime(item.DATETIME).Subtract(Convert.ToDateTime(item.DATETIME)).Hours >= 23 ? true : false,
                            };
                            list.Add(eventTimeSlots);
                        }
                    }
                }
                return list;
            }
        }
    }
}
